﻿#include <WS2tcpip.h>
#include <tchar.h>
#include "Const.h"
#include "Server.h"

// 函数声明
static void Server_Delete(Server*);
static void Server_CreateDatabase(Server*);
static void Server_HandleAddFriendRequest(Server*, AddFriendRequest*, SOCKET);
static void Server_HandleAddFriendResult(Server*, AddFriendResult*);
static void Server_HandleChat(Server*, ChatInfo*);
static void Server_HandleLogoff(Server*, LogoffRequest*);
static void Server_HandleLogon(Server*, LogonRequest*, SOCKET);
static void Server_HandleReg(Server*, RegRequest*, SOCKET);
static void Server_OnGetMessageFromClient(Server*, ImProtocol*, SOCKET);
static void Server_RemoveUser(Server*, SOCKET);
static void Server_SendData(SOCKET, void*, int);
static BOOL Server_Start(Server*);
static DWORD WINAPI Server_Thread(LPVOID);

/**
 * 创建服务器。
 * @return 服务器
 */
Server* New_Server() {
    Server* server = (Server*)calloc(1, sizeof(Server));
    WSADATA wsaData = { 0 };

    // 初始化数据
    server->mOnlineUsers = New_OnlineUserList();

    // 初始化函数
    server->deleteSelf = Server_Delete;
    server->start = Server_Start;

    // 创建数据库
    Server_CreateDatabase(server);

    // 初始化网络
    WSAStartup(MAKEWORD(2, 2), &wsaData);

    return server;
}

/**
 * 删除服务器。
 * @param server    服务器
 */
static void Server_Delete(Server* server) {
    // 关闭套接字
    closesocket(server->mSocket);

    // 关闭数据库
    sqlite3_close_v2(server->mDatabase);

    // 清空在线用户列表
    server->mOnlineUsers->removeAll(server->mOnlineUsers);
    server->mOnlineUsers->deleteSelf(server->mOnlineUsers);

    // 反初始化网络
    WSACleanup();
}

/**
 * 创建数据库。
 * @param server    服务器
 */
static void Server_CreateDatabase(Server* server) {
    sqlite3_stmt* query = NULL;         // 数据库查询
    TCHAR sql[STRING_BUF_LEN] = { 0 };  // 查询语句

    // 打开数据库
    sqlite3_open16(DB_PATH, &server->mDatabase);

    // 创建表
    /* 用户表 */
    _stprintf_s(sql, STRING_BUF_LEN, _T("CREATE TABLE IF NOT EXISTS %s(%s TEXT PRIMARY KEY,%s TEXT,%s INTEGER)"),
        TABLE_USERS, FIELD_NAME, FIELD_PASSWORD, FIELD_ICON_INDEX);
    sqlite3_prepare16_v2(server->mDatabase, sql, -1, &query, NULL);
    sqlite3_step(query);
    sqlite3_finalize(query);

    /* 好友表 */
    _stprintf_s(sql, STRING_BUF_LEN, _T("CREATE TABLE IF NOT EXISTS %s(%s TEXT,%s TEXT)"),
        TABLE_FRIENDS, FIELD_OWNER, FIELD_FRIEND_NAME);
    sqlite3_prepare16_v2(server->mDatabase, sql, -1, &query, NULL);
    sqlite3_step(query);
    sqlite3_finalize(query);

    /* 离线聊天表 */
    _stprintf_s(sql, STRING_BUF_LEN, _T("CREATE TABLE IF NOT EXISTS %s(%s TEXT,%s TEXT,%s TEXT,%s TEXT)"),
        TABLE_OFFLINE_CHAT, FIELD_DST_USER, FIELD_SRC_USER, FIELD_CONTENT, FIELD_TIME);
    sqlite3_prepare16_v2(server->mDatabase, sql, -1, &query, NULL);
    sqlite3_step(query);
    sqlite3_finalize(query);

    /* 离线添加好友表 */
    _stprintf_s(sql, STRING_BUF_LEN, _T("CREATE TABLE IF NOT EXISTS %s(%s TEXT,%s TEXT,%s INTEGER)"),
        TABLE_OFFLINE_ADD_FRIEND, FIELD_SRC_USER, FIELD_DST_USER, FIELD_RESULT);
    sqlite3_prepare16_v2(server->mDatabase, sql, -1, &query, NULL);
    sqlite3_step(query);
    sqlite3_finalize(query);
}

/**
 * 处理添加好友请求。
 * @param server    服务器
 * @param request   添加好友请求
 * @param client    客户端
 */
static void Server_HandleAddFriendRequest(Server* server, AddFriendRequest* request, SOCKET client) {
    sqlite3_stmt* query = NULL;
    TCHAR sql[STRING_BUF_LEN] = { 0 };
    AddFriendResult* result = NULL;
    SOCKET friendUser = INVALID_SOCKET;

    // 检查目标用户是否存在
    _stprintf_s(sql, STRING_BUF_LEN, _T("SELECT * FROM %s WHERE %s='%s'"), TABLE_USERS, FIELD_NAME, request->mDstUsername);
    sqlite3_prepare16_v2(server->mDatabase, sql, -1, &query, NULL);
    if (sqlite3_step(query) == SQLITE_DONE) {
        // 查无此人，通知源用户
        result = New_AddFriendResult(0, request->mDstUsername, USER_NOT_FOUND, request->mSrcUsername);
        Server_SendData(client, result, sizeof(AddFriendResult));
        sqlite3_finalize(query);
        free(result);
        return;
    }
    sqlite3_finalize(query);

    // 检查是否已经是好友了
    _stprintf_s(sql, STRING_BUF_LEN, _T("SELECT * FROM %s WHERE %s='%s' AND %s='%s'"), TABLE_FRIENDS, FIELD_OWNER, request->mSrcUsername, FIELD_FRIEND_NAME, request->mDstUsername);
    sqlite3_prepare16_v2(server->mDatabase, sql, -1, &query, NULL);
    if (sqlite3_step(query) != SQLITE_DONE) {
        // 已经是好友了，通知源用户
        result = New_AddFriendResult(0, request->mDstUsername, ALREADY_BE_FRIENDS, NULL);
        Server_SendData(client, result, sizeof(AddFriendResult));
        free(result);
        return;
    }
    sqlite3_finalize(query);

    // 如果目标用户不在线，则将请求信息插入到数据库中
    friendUser = server->mOnlineUsers->find(server->mOnlineUsers, request->mDstUsername);
    if (friendUser == INVALID_SOCKET) {
        _stprintf_s(sql, STRING_BUF_LEN, _T("INSERT INTO %s(%s,%s) VALUES('%s','%s')"), 
            TABLE_OFFLINE_ADD_FRIEND, FIELD_SRC_USER, FIELD_DST_USER, request->mSrcUsername, request->mDstUsername);
        sqlite3_prepare16_v2(server->mDatabase, sql, -1, &query, NULL);
        sqlite3_step(query);
        sqlite3_finalize(query);
        return;
    }

    // 向目标用户发送请求
    Server_SendData(friendUser, request, sizeof(AddFriendRequest));
}

/**
 * 处理添加好友结果。
 * @param server    服务器
 * @param result    添加好友结果
 */
static void Server_HandleAddFriendResult(Server* server, AddFriendResult* result) {
    sqlite3_stmt* query = NULL;
    TCHAR sql[STRING_BUF_LEN] = { 0 };
    SOCKET friendUser = INVALID_SOCKET;

    // 如果结果是同意，则将相关信息写到好友表中
    if (result->mResultCode == ADD_FRIEND_ALLOW) {
        _stprintf_s(sql, STRING_BUF_LEN, _T("INSERT INTO %s VALUES('%s','%s')"), TABLE_FRIENDS, result->mSrcUsername, result->mDstUsername);
        sqlite3_prepare16_v2(server->mDatabase, sql, -1, &query, NULL);
        sqlite3_step(query);
        sqlite3_finalize(query);

        _stprintf_s(sql, STRING_BUF_LEN, _T("INSERT INTO %s VALUES('%s','%s')"), TABLE_FRIENDS, result->mDstUsername, result->mSrcUsername);
        sqlite3_prepare16_v2(server->mDatabase, sql, -1, &query, NULL);
        sqlite3_step(query);
        sqlite3_finalize(query);
    }

    // 如果目标用户不在线，则将结果信息插入到数据库中
    friendUser = server->mOnlineUsers->find(server->mOnlineUsers, result->mSrcUsername);
    if (friendUser == INVALID_SOCKET) {
        _stprintf_s(sql, STRING_BUF_LEN, _T("INSERT INTO %s VALUES('%s','%s','%d')"), TABLE_OFFLINE_ADD_FRIEND, result->mSrcUsername, result->mDstUsername, result->mResultCode);
        sqlite3_prepare16_v2(server->mDatabase, sql, -1, &query, NULL);
        sqlite3_step(query);
        sqlite3_finalize(query);
        return;
    }

    // 向目标用户发送结果
    Server_SendData(friendUser, result, sizeof(AddFriendResult));
}

/**
 * 处理聊天。
 * @param server    服务器
 * @param chatInfo  聊天信息
 */
static void Server_HandleChat(Server* server, ChatInfo* chatInfo) {
    sqlite3_stmt* query = NULL;
    TCHAR sql[STRING_BUF_LEN] = { 0 };
    SOCKET friendUser = INVALID_SOCKET;
    OnlineUser* onlineUser = NULL;

    // 处理群发消息
    if (_tcscmp(chatInfo->mDstUsername, MULTI_CHAT) == 0) {
        for (onlineUser = server->mOnlineUsers->mHead; onlineUser != NULL; onlineUser = onlineUser->next) {
            // 跳过自己，向其它用户发送聊天信息
            if (_tcscmp(chatInfo->mSrcUsername, onlineUser->username) != 0) {
                Server_SendData(onlineUser->sock, chatInfo, sizeof(ChatInfo));
            }
        }
        return;
    }

    // 如果目标用户不在线，则将聊天信息插入到数据库中
    friendUser = server->mOnlineUsers->find(server->mOnlineUsers, chatInfo->mDstUsername);
    if (friendUser == INVALID_SOCKET) {
        _stprintf_s(sql, STRING_BUF_LEN, _T("INSERT INTO %s VALUES('%s','%s','%s','%s')"),
            TABLE_OFFLINE_CHAT, chatInfo->mDstUsername, chatInfo->mSrcUsername, chatInfo->mContent, chatInfo->mTime);
        sqlite3_prepare16_v2(server->mDatabase, sql, -1, &query, NULL);
        sqlite3_step(query);
        sqlite3_finalize(query);
        return;
    }

    // 发送给目标用户
    Server_SendData(friendUser, chatInfo, sizeof(ChatInfo));
}

/**
 * 处理离线请求。
 * @param server    服务器
 * @param request   离线请求
 */
static void Server_HandleLogoff(Server* server, LogoffRequest* request) {
    OnlineUser* user = NULL;

    // 将该用户从在线列表移除
    server->mOnlineUsers->removeByName(server->mOnlineUsers, request->mUsername);

    // 广播该用户的离线请求
    for (user = server->mOnlineUsers->mHead; user != NULL; user = user->next) {
        if (user->sock != INVALID_SOCKET && user->username[0] != '\0') {
            Server_SendData(user->sock, request, sizeof(LogoffRequest));
        }
    }
}

/**
 * 处理登录请求。
 * @param server    服务器
 * @param request   登录请求
 * @param client    客户端
 */
static void Server_HandleLogon(Server* server, LogonRequest* request, SOCKET client) {
    LogonResult* logonResult = New_LogonResult();
    sqlite3_stmt* query = NULL;
    TCHAR sql[STRING_BUF_LEN] = { 0 };
    LPCTSTR password = NULL;

    int friendCount = 0;
    FriendLogon* friendLogon = NULL;
    LPCTSTR friendName = NULL;
    SOCKET friendUser = INVALID_SOCKET;
    sqlite3_stmt* iconIndexQuery = NULL;
    BOOL isOnline = FALSE;

    LPCTSTR srcUsername = NULL;
    LPCTSTR content = NULL;
    LPCTSTR time = NULL;
    AddFriendRequest* addFriendRequest = NULL;
    AddFriendResult* addFriendResult = NULL;
    ChatInfo* chatInfo = NULL;

    // 检查该用户是否已经登录
    if (server->mOnlineUsers->find(server->mOnlineUsers, request->mUserInfo.mUsername) != INVALID_SOCKET) {
        // 已经登录了
        logonResult->mResultCode = USER_ALREADY_LOGON;
        Server_SendData(client, logonResult, sizeof(LogonResult));
        free(logonResult);
        return;
    }

    // 从数据库中查找该用户
    _stprintf_s(sql, STRING_BUF_LEN, _T("SELECT * FROM %s WHERE %s='%s'"), TABLE_USERS, FIELD_NAME, request->mUserInfo.mUsername);
    sqlite3_prepare16_v2(server->mDatabase, sql, -1, &query, NULL);
    if (sqlite3_step(query) == SQLITE_DONE) {
        // 查无此人
        sqlite3_finalize(query);
        logonResult->mResultCode = USER_NOT_FOUND;
        Server_SendData(client, logonResult, sizeof(LogonResult));
        free(logonResult);
        return;
    }

    // 比对密码
#ifdef _UNICODE
    password = (LPCTSTR)sqlite3_column_text16(query, 1);
#else
    password = (LPCTSTR)sqlite3_column_text(query, 1);
#endif
    if (_tcscmp(request->mUserInfo.mPassword, password) != 0) {
        // 密码不正确
        sqlite3_finalize(query);
        logonResult->mResultCode = PASSWORD_WRONG;
        Server_SendData(client, logonResult, sizeof(LogonResult));
        free(logonResult);
        return;
    }
    
    // 登录成功，获取该用户的相关信息
    logonResult->mResultCode = LOGON_SUCCEEDED;
    logonResult->mIconIndex = sqlite3_column_int(query, 2);
    sqlite3_finalize(query);

    // 获取该用户的好友列表
    _stprintf_s(sql, STRING_BUF_LEN, _T("SELECT * FROM %s WHERE %s='%s'"), TABLE_FRIENDS, FIELD_OWNER, request->mUserInfo.mUsername);
    sqlite3_prepare16_v2(server->mDatabase, sql, -1, &query, NULL);

    for (friendCount = 0; sqlite3_step(query) == SQLITE_ROW; friendCount++) {
#ifdef _UNICODE
        friendName = (LPCTSTR)sqlite3_column_text16(query, 1);
#else
        friendName = (LPCTSTR)sqlite3_column_text(query, 1);
#endif
        _tcscpy_s(logonResult->mFriends[friendCount].mUsername, USERNAME_BUF_LEN, friendName);

        _stprintf_s(sql, STRING_BUF_LEN, _T("SELECT %s FROM %s WHERE %s='%s'"), FIELD_ICON_INDEX, TABLE_USERS, FIELD_NAME, friendName);
        sqlite3_prepare16_v2(server->mDatabase, sql, -1, &iconIndexQuery, NULL);
        sqlite3_step(iconIndexQuery);
        logonResult->mFriends[friendCount].mIconIndex = sqlite3_column_int(iconIndexQuery, 0);
        sqlite3_finalize(iconIndexQuery);

        friendUser = server->mOnlineUsers->find(server->mOnlineUsers, friendName);
        isOnline = (friendUser != INVALID_SOCKET);
        logonResult->mFriendsOnline[friendCount] = isOnline;

        // 如果好友在线，则向好友发送通知
        if (isOnline) {
            friendLogon = New_FriendLogon(request->mUserInfo.mUsername);
            Server_SendData(friendUser, friendLogon, sizeof(FriendLogon));
            free(friendLogon);
        }
    }
    sqlite3_finalize(query);
    logonResult->mFriendCount = friendCount;

    // 发送登录结果
    Server_SendData(client, logonResult, sizeof(LogonResult));
    free(logonResult);

    // 查询是否有和该用户相关的离线添加好友请求，有则发送
    _stprintf_s(sql, STRING_BUF_LEN, _T("SELECT * FROM %s WHERE %s='%s' AND %s IS NULL"), 
        TABLE_OFFLINE_ADD_FRIEND, FIELD_DST_USER, request->mUserInfo.mUsername, FIELD_RESULT);
    sqlite3_prepare16_v2(server->mDatabase, sql, -1, &query, NULL);
    while (sqlite3_step(query) == SQLITE_ROW) {
#ifdef _UNICODE
        srcUsername = (LPCTSTR)sqlite3_column_text16(query, 0);
#else
        srcUsername = (LPCTSTR)sqlite3_column_text(query, 0);
#endif
        _stprintf_s(sql, STRING_BUF_LEN, _T("SELECT %s FROM %s WHERE %s='%s'"), FIELD_ICON_INDEX, TABLE_USERS, FIELD_NAME, srcUsername);
        sqlite3_prepare16_v2(server->mDatabase, sql, -1, &iconIndexQuery, NULL);
        sqlite3_step(iconIndexQuery);

        addFriendRequest = New_AddFriendRequest(request->mUserInfo.mUsername, sqlite3_column_int(iconIndexQuery, 0), srcUsername);
        Server_SendData(client, addFriendRequest, sizeof(AddFriendRequest));
        sqlite3_finalize(iconIndexQuery);
    }
    sqlite3_finalize(query);

    // 删除数据库中的离线添加好友请求
    _stprintf_s(sql, STRING_BUF_LEN, _T("DELETE FROM %s WHERE %s='%s'"), TABLE_OFFLINE_ADD_FRIEND, FIELD_DST_USER, request->mUserInfo.mUsername);
    sqlite3_prepare16_v2(server->mDatabase, sql, -1, &query, NULL);
    sqlite3_step(query);
    sqlite3_finalize(query);

    // 查询是否有和该用户相关的离线添加好友结果，有则发送
    _stprintf_s(sql, STRING_BUF_LEN, _T("SELECT * FROM %s WHERE %s='%s'"), TABLE_OFFLINE_ADD_FRIEND, FIELD_SRC_USER, request->mUserInfo.mUsername);
    sqlite3_prepare16_v2(server->mDatabase, sql, -1, &query, NULL);
    LPCTSTR dstUsername;
    while (sqlite3_step(query) == SQLITE_ROW) {
#ifdef _UNICODE
        dstUsername = (LPCTSTR)sqlite3_column_text16(query, 1);
#else
        dstUsername = (LPCTSTR)sqlite3_column_text(query, 1);
#endif
        addFriendResult = New_AddFriendResult(-1, dstUsername, (ResultCode)sqlite3_column_int(query, 2), request->mUserInfo.mUsername);
        Server_SendData(client, addFriendResult, sizeof(AddFriendResult));
        free(addFriendResult);
    }
    sqlite3_finalize(query);

    // 删除数据库中的离线添加好友结果
    _stprintf_s(sql, STRING_BUF_LEN, _T("DELETE FROM %s WHERE %s='%s'"), TABLE_OFFLINE_ADD_FRIEND, FIELD_SRC_USER, request->mUserInfo.mUsername);
    sqlite3_prepare16_v2(server->mDatabase, sql, -1, &query, NULL);
    sqlite3_step(query);
    sqlite3_finalize(query);

    // 查询是否有和该用户相关的离线聊天消息，有则发送
    _stprintf_s(sql, STRING_BUF_LEN, _T("SELECT * FROM %s WHERE %s='%s'"), TABLE_OFFLINE_CHAT, FIELD_DST_USER, request->mUserInfo.mUsername);
    sqlite3_prepare16_v2(server->mDatabase, sql, -1, &query, NULL);
    while (sqlite3_step(query) == SQLITE_ROW) {
#ifdef _UNICODE
        srcUsername = (LPCTSTR)sqlite3_column_text16(query, 1);
        content = (LPCTSTR)sqlite3_column_text16(query, 2);
        time = (LPCTSTR)sqlite3_column_text16(query, 3);
#else
        srcUsername = (LPCTSTR)sqlite3_column_text(query, 1);
        content = (LPCTSTR)sqlite3_column_text(query, 2);
        time = (LPCTSTR)sqlite3_column_text(query, 3);
#endif
        chatInfo = New_ChatInfo(content, request->mUserInfo.mUsername, srcUsername, time);
        Server_SendData(client, chatInfo, sizeof(ChatInfo));
        free(chatInfo);
    }
    sqlite3_finalize(query);

    // 删除数据库中的离线聊天信息
    _stprintf_s(sql, STRING_BUF_LEN, _T("DELETE FROM %s WHERE %s='%s'"), TABLE_OFFLINE_CHAT, FIELD_DST_USER, request->mUserInfo.mUsername);
    sqlite3_prepare16_v2(server->mDatabase, sql, -1, &query, NULL);
    sqlite3_step(query);
    sqlite3_finalize(query);

    // 将该用户加入在线列表
    server->mOnlineUsers->setAt(server->mOnlineUsers, client, request->mUserInfo.mUsername);
}

/**
 * 处理注册请求。
 * @param server    服务器
 * @param request   注册请求
 * @param client    客户端
 */
static void Server_HandleReg(Server* server, RegRequest* request, SOCKET client) {
    RegResult* regResult = New_RegResult();
    sqlite3_stmt* query = NULL;
    TCHAR sql[STRING_BUF_LEN] = { 0 };

    // 将该用户信息插入到数据库中
    _stprintf_s(sql, STRING_BUF_LEN, _T("INSERT INTO %s VALUES('%s','%s','%d')"), TABLE_USERS,
        request->mUserInfo.mUsername, request->mUserInfo.mPassword, request->mUserInfo.mIconIndex);
    sqlite3_prepare16_v2(server->mDatabase, sql, -1, &query, NULL);
    if (sqlite3_step(query) != SQLITE_DONE) {
        // 该用户已存在
        sqlite3_finalize(query);
        regResult->mResultCode = USER_EXISTS;
        Server_SendData(client, regResult, sizeof(RegResult));
        free(regResult);
        return;
    }
    sqlite3_finalize(query);

    // 发送结果
    regResult->mResultCode = REG_SUCCEEDED;
    Server_SendData(client, regResult, sizeof(RegResult));

    // 将该用户加入到在线列表中
    server->mOnlineUsers->setAt(server->mOnlineUsers, client, request->mUserInfo.mUsername);

    free(regResult);
}

/**
 * 处理客户端发送来的数据。
 * @param server    服务器
 * @param pro       协议
 * @param client    客户端
 */
static void Server_OnGetMessageFromClient(Server* server, ImProtocol* pro, SOCKET client) {
    switch (pro->mType) {
        case ADD_FRIEND_REQUEST:
            Server_HandleAddFriendRequest(server, (AddFriendRequest*)pro, client);
            break;
        case ADD_FRIEND_RESULT:
            Server_HandleAddFriendResult(server, (AddFriendResult*)pro);
            break;
        case CHAT:
            Server_HandleChat(server, (ChatInfo*)pro);
            break;
        case LOGOFF:
            Server_HandleLogoff(server, (LogoffRequest*)pro);
            break;
        case LOGON:
            Server_HandleLogon(server, (LogonRequest*)pro, client);
            break;
        case REG:
            Server_HandleReg(server, (RegRequest*)pro, client);
            break;
    }
}

/**
 * 删除用户。
 * @param server        服务器
 * @param clientSocket  客户端套接字
 */
static void Server_RemoveUser(Server* server, SOCKET clientSocket) {
    OnlineUser* user = NULL;                // 在线用户
    LogoffRequest* logoffRequest = NULL;    // 离线请求

    // 发送离线请求
    user = server->mOnlineUsers->findBySocket(server->mOnlineUsers, clientSocket, NULL);
    if (user->username[0] != '\0') {
        logoffRequest = New_LogoffRequest(user->username);
        Server_HandleLogoff(server, logoffRequest);
        free(logoffRequest);
    }

    // 删除该用户
    server->mOnlineUsers->removeBySocket(server->mOnlineUsers, clientSocket);
    closesocket(clientSocket);
}

/**
 * 发送数据。
 * @param client    客户端
 * @param pro       协议
 * @param dataSize  数据长度
 */
static void Server_SendData(SOCKET client, void* pro, int dataSize) {
    // 发送数据长度
    send(client, (const char*)&dataSize, sizeof(dataSize), 0);

    // 发送数据
    send(client, pro, dataSize, 0);

    // 防止发送过快导致客户端无法响应
    Sleep(100);
}

/**
 * 开启服务。
 * @param server    服务器
 * @return 成功则返回 TRUE，否则返回 FALSE
 */
static BOOL Server_Start(Server* server) {
    SOCKADDR_IN serverAddr = { AF_INET };
    HANDLE threadHandle = NULL;
    int result = 0;

    // 创建套接字
    server->mSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

    // 绑定端口
    inet_pton(AF_INET, SERVER_IP, &(serverAddr.sin_addr));
    serverAddr.sin_port = htons(SERVER_PORT);
    result = bind(server->mSocket, (SOCKADDR*)&serverAddr, sizeof(serverAddr));
    if (result == SOCKET_ERROR) {
        return result;
    }

    // 侦听
    result = listen(server->mSocket, SOMAXCONN);
    if (result == SOCKET_ERROR) {
        return FALSE;
    }

    // 开启接收数据的线程
    threadHandle = CreateThread(NULL, 0, Server_Thread, server, 0, 0);
    return CloseHandle(threadHandle);
}

/**
 * 服务器线程。
 * @param param 服务器
 * @return 总是零
 */
static DWORD WINAPI Server_Thread(LPVOID param) {
    Server* server = (Server*)param;        // 服务器
    u_int i = 0;                            // 循环变量
    OnlineUser* user = NULL;                // 在线用户
    int size = 0;                           // 数据长度
    char* buffer = NULL;                    // 接收数据的缓存
    int result = 1;                         // 返回值
    SOCKET clientSocket = INVALID_SOCKET;   // 客户端套接字
    fd_set fdRead = { 0 };                  // 套接字集合
    ImProtocol* pro = NULL;                 // 协议

    while (TRUE) {
        // 将服务器套接字加入到 fdRead 中
        FD_ZERO(&fdRead);
        FD_SET(server->mSocket, &fdRead);

        // 将所有客户端套接字加入到 fdRead 中
        for (user = server->mOnlineUsers->mHead; user != NULL; user = user->next) {
            FD_SET(user->sock, &fdRead);
        }

        // 选择所有可读的客户端套接字
        result = select(0, &fdRead, NULL, NULL, NULL);
        if (result == SOCKET_ERROR) {
            break;
        }

        // 遍历所有套接字，找到可读的
        for (i = 0; i < fdRead.fd_count; i++) {
            if (fdRead.fd_array[i] == server->mSocket) {
                // 如果是服务器的套接字，则接受用户连接
                // 将用户套接字加入到在线用户列表中
                clientSocket = accept(server->mSocket, NULL, NULL);
                if (clientSocket == SOCKET_ERROR) {
                    return 0;
                }
                server->mOnlineUsers->addSocket(server->mOnlineUsers, clientSocket);
            } else {
                // 如果是客户端的套接字，则接收数据
                // 接收数据长度
                result = recv(fdRead.fd_array[i], (char*)&size, sizeof(size), 0);
                if (result <= 0) {
                    Server_RemoveUser(server, fdRead.fd_array[i]);
                    continue;
                }

                // 接收数据
                buffer = (char*)calloc(1, size);
                result = recv(fdRead.fd_array[i], buffer, size, 0);
                if (result <= 0) {
                    Server_RemoveUser(server, fdRead.fd_array[i]);
                    free(buffer);
                    continue;
                }

                // 将数据转换成协议
                pro = (ImProtocol*)buffer;

                // 处理协议
                Server_OnGetMessageFromClient(server, pro, fdRead.fd_array[i]);

                // 释放缓存
                free(buffer);
            }
        }
    }

    return 0;
}
